#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <fcntl.h>
#include "gaia_common.h"
#include "gaia_process_request.h"
#include "gaia_reply_info.h"
#include "cJSON.h"


/*******************************************************************
 * 函数名：gaia_process_request 
 * 函数功能：处理请求
 * 返回值：成功 0，失败 -1
 * 参数：connect_fd创建好的sock句柄,client_addr请求端IP
 ******************************************************************/
int gaia_process_request(int *connect_fd,struct sockaddr_in *client_addr)
{
  //任务号
  int taskid = 0;
  //nextid
  int host_next_id = 0;
  //startime
  int starttime = 0;

   /* 结构体用于存放主机信息，在这里是需要获取task_type  */
  HOST *hostinfo;
  hostinfo  = (HOST *)malloc(sizeof(HOST));
 
  /* 无法申请内存，造成无法获取主机信息 */
  if(NULL == hostinfo)
  {
    fprintf(stderr,"hostinfo malloc fail!\n");
    //sprintf(respo_error,tmp_respo_error,"error");
    //gaia_callback(respo_error);
    return 1;
  }

  printf("gaia server test!\n");

  /* 返回头 */
  char *str =  "HTTP/1.1 200 OK\r\nServer:ZRIT Gaia/Linux(1.0)\r\n";
  char *err_str = "HTTP/1.1 403 Forbidden\r\nServer:ZRIT Gaia/Linux(1.0)\r\n";
  //char *test_str = "\r\n\r\n<html><head></head><body>404 File not found<br/>Please check your url,and try it again!</body></html>";
  //char *test_str = "\r\n\r\n<html><head></head><body>task_id:0,status:80,msg:\"just test\" </body></html>";
  char *test_str = "\r\n\r\n<html><head></head><body>Hello,cassie!</body></html>";
  //register int send_bytes = strlen(str);

  /* 缓冲区设置 */
  char recv_buf[RECV_BUFFER_SIZE + 1];
  unsigned char send_buf[SEND_BUFFER_SIZE + 1];
  char post_uri_buf[256];

  /* 清空缓冲区内容 */
  memset(recv_buf,'\0',sizeof(recv_buf));
  memset(send_buf,'\0',sizeof(send_buf));

  /* 设置uri缓冲区 */
  char uri_buf[URI_SIZE + 1];
  memset(uri_buf,'\0',sizeof(uri_buf));

  /* 设置任务名 */
  char task_name[TASK_SIZE + 1];
  memset(task_name,'\0',sizeof(task_name));

  /* select 相关设置 */
  int maxfd = *connect_fd + 1;
  fd_set read_set;
  FD_ZERO(&read_set);
  
  /* 设置select超时时间 */
  struct timeval timeout;
  timeout.tv_sec = TIME_OUT_SEC;
  timeout.tv_usec = TIME_OUT_USEC;

  int flag  = 1;
  int res = 0;

  /* 接收和发送字节数 */
  int read_bytes = 0;
  int send_bytes = 0;

  /* 设置端口集 */
  FD_SET(*connect_fd,&read_set);

  while(flag)
  {
    /* 这里只检查可读的fd */
    res = select(maxfd,&read_set,NULL,NULL,&timeout);
    switch(res)
    {
      case -1:
        perror("select() error.");
        close(*connect_fd);
        return -1;
        break;
      case 0:
        fprintf(stderr,"select timeout!\n");
        continue;
        break;
    default:
        if(FD_ISSET(*connect_fd,&read_set))
        {
          memset(recv_buf,'\0',sizeof(recv_buf));
          if((read_bytes = recv(*connect_fd,recv_buf,RECV_BUFFER_SIZE,0)) == 0)
            return 0;   //客户端关闭连接
          else if(read_bytes > 0)
          {
            memset(uri_buf,'\0',sizeof(uri_buf));
            memset(post_uri_buf,'\0',sizeof(post_uri_buf));
            /* 获取post数据 */
            gaia_get_post(recv_buf,post_uri_buf); 
            /* 获取task_name */
            if( gaia_get_uri(recv_buf,task_name) == NULL)
            {
              fprintf(stderr,"get uri fail!\n");
              return -1;
            }

            flag  = 0; //处理完毕，将循环条件设置为fail,不然会导致select超时
          
          }
        }  
    }
    
  }


  /* 解析Post过来的数据 */
  if( strcmp(task_name,"getstatus") == 0)
  {
    gaia_parse_post_data(2,post_uri_buf,&hostinfo);
    printf("task_id  = %d\n",hostinfo->taskid);
  }else {
    gaia_parse_post_data(0,post_uri_buf,&hostinfo);
  }
  printf("gaia server test 00000!\n");

  //获取unixtime
  gaia_get_unixtime(&starttime);
  //获取hostid
  gaia_DBselect_nextid(0,&host_next_id);
  //获取taskid
  gaia_get_taskid(&taskid);

  /* just debug
  printf("starttime = %d,host_next_id = %d,taskid = %d\n",starttime,host_next_id,taskid);
  printf("task_name: %s\n",task_name);
  printf("deploy_type = %s\n",hostinfo->deploy_type);
  */

  //接到非查询请求，写入首次状态
  if( strcmp(task_name,"getstatus") != 0)
  {
    gaia_write_task_status_frist(taskid,hostinfo->deploy_type,host_next_id,starttime,0);
    //首次返回
    gaia_reply_info(connect_fd,taskid,0,"Task start!");
  }

  //释放内存
  free(hostinfo);

  /* 入口选择 */
  if( (strcmp(task_name,"create")) == 0 )  //添加主机
  {
     //printf("uri = %s\n",post_uri_buf);
     //printf("add host!\n");
     printf("taskid = %d\n",taskid);

     // 在添加主机的之后，会自动收集该主机的硬件、系统信息,并将数据放到数据库 
     int process_ret = gaia_add_host(taskid,post_uri_buf);
     printf("process_ret = %d\n",process_ret);
  }else if( (strcmp(task_name,"getstatus")) == 0 ){  //查询任务进度
     printf("getstatus\n");
     //gaia_get_host_status(1,"this is test");
     gaia_task_status(connect_fd,hostinfo->taskid);
  }else if( (strcmp(task_name,"task")) == 0){       //执行任务
     printf("operation a task!\n");
     //gaia_task(1,"uptime");
     gaia_task(post_uri_buf);
  }else {
     //printf("111111111111\n");
     //send_bytes = strlen(test_str);
     //memcpy(send_buf,test_str,send_bytes);
     //send(*connect_fd, send_buf, send_bytes, 0);
     //close(*connect_fd);
     gaia_reply_info(connect_fd,155,20,"just test");
  }

  printf("just test!\n");
 
  gaia_reply_info(connect_fd,taskid,100,"Task finish!");
  //close(*connect_fd);
  return 0;
}


/* 
 * 函数功能：提取http请求中的uri 
 * 返回值：提取成功返回uri，不成功，返回NULL
 * 参数：request得到的请求字符串，uri_buf用于
 * 存储获取到的uri,并且作为函数返回。
 */

/*
 * 由于http请求，在server端得到的字符串如下形式：
 * “GET /index.html HTTP/1.1”，所以，要处理请求
 * 必须先得到uri，进而得到传递的参数 
 */
char *gaia_get_uri(char *request,char *uri_buf)
{
  //printf("request = %s\n",request);
  int index = 0;
  while( (request[index] != '/') && (request[index] != '\0') )
  {
    index++;
  }
  int base = index;
  while( ((index - base) < URI_SIZE) && (request[index] != ' ') && (request[index] != '\0') )
  {
    index++;
  }
  if( (index - base) >= URI_SIZE)
  {
    fprintf(stderr, "error: too long of uri request.\n");
    return NULL;
  }
  if((request[index - 1] == '/') && (request[index] == ' '))
  {
    strcpy(uri_buf, "index.html");
    return uri_buf;
  }
  strncpy(uri_buf, request + base + 1, index - base - 1);
  printf("uri_buf001 = %s\n",uri_buf);
  return uri_buf;

}

//此函数已失效，用gaia_get_uri替代
/* 获取任务名,用于决定如何进行操作 */
char *gaia_get_task(const char *uri,char *task_name)
{
  int index = 0;
  char temp[123];

  //while( (uri[index] != '/') || (uri[index] != '?') )
  while( uri[index] != '/' )
   index++;

  memcpy(task_name,uri,index);

  return task_name;
}


int gaia_get_post(const char *request,char *post_uri_buf)
{
   int index = 0;
   int i = 0;
   char post_data[1024];
   while(request[index] != '{')
     index++;
   int base = index;

   while( ( request[index] != '\0') && ( index - base) < 1024 )
  {
      post_data[i] = request[index];
      i++;
      index++;
  } 

  memcpy(post_uri_buf,post_data,sizeof(post_data));

  return 0;
}
